import * as path from "path";
import NodeID3 = require("node-id3");

import { initDB } from ".";
import { VIRTUAL_PATH_PREFIX } from "../media";
import { existCacheLabel, IDataMP3 } from "./media";
import { COL_MEDIA, COL_MEDIA_CACHE } from "./config";

/**
 * 缓存数据条目
 */
export interface ICache {
	key: string;
	label: string;
	tags: string[];
}

/**
 * 生成 Audio label
 */
export function createAudioLabel(tags: NodeID3.Tags) {
	const { album, artist, title } = tags;
	return `@${artist}/${album}/${title}`;
}

/**
 * 生成 Audio label
 */
export function createAudioLabelFromBuf(buf: Buffer) {
	const tags = NodeID3.read(buf);
	return createAudioLabel(tags);
}

/**
 * 生成 Video label
 */
export function createVideoLabel(tags: IDataMP3) {
	const { virtualPath } = tags;
	return `@${virtualPath},VIDEO_TAG`;
}

/**
 * 生成 Video label
 */
export function createVideoLabelFromFilename(file: string) {
	const virtualPath = genVitualPath(file);
	return `@${virtualPath},VIDEO_TAG`;
}

export function genVitualPath(file: string) {
	return path.join(VIRTUAL_PATH_PREFIX, path.basename(file));
}

/**
 * 读取所有MP3缓存数据
 */
export async function getCache(params?: Partial<ICache>) {
	const db = await initDB();
	const cache: ICache[] = [];
	const mp3 = db.collection(COL_MEDIA_CACHE);

	const cursor = mp3.find(params);
	const array = await cursor.toArray();

	if (!array.length) {
		return [];
	}
	array.forEach((item) => {
		cache.push(item as unknown as ICache);
	});

	return cache;
}

/**
 * 增加缓存数据
 *
 * @returns 0 为 Cache 已存在且不添加，1 为成功添加
 */
export async function insertCache(item: ICache) {
	const { label } = item;
	const exist = await existCacheLabel(label);

	if (exist === 0) {
		const db = await initDB();
		const cacheDB = db.collection(COL_MEDIA_CACHE);
		const cursor = cacheDB.insertOne(item);
		return 1;
	} else {
		return 0;
	}
}

/**
 * 储存所有缓存数据
 */
export async function storeCache() {
	const db = await initDB();
	const mp3 = db.collection(COL_MEDIA);
	const cache = db.collection(COL_MEDIA_CACHE);
	(await mp3.find().toArray()).forEach(async (item) => {
		const mp3Item = item as unknown as IDataMP3;
		const key = mp3Item.key;
		const tags = mp3Item.tags;
		const label = mp3Item.label;
		await cache.updateOne({ key }, { $set: { tags, label } });
	});
}

/**
 * 储存指定 key 的缓存数据
 */
export async function storeCacheByKey(key: string) {
	const db = await initDB();
	const media = db.collection(COL_MEDIA);
	const cache = db.collection(COL_MEDIA_CACHE);
	const { tags, label } = (await media.findOne({ key })) as unknown as IDataMP3;
	await cache.updateOne({ key }, { $set: { tags, label } });
}

/**
 *
 * @param cache 缓存数据库数据
 * @param targetLabel 目标label
 * @returns 合法的Cache单条数据
 */
export function getCacheItem(cache: ICache[], targetLabel: string): ICache {
	for (const { key, label, tags } of cache) {
		if (targetLabel === label) {
			return { tags: tags ?? [], key, label: targetLabel };
		}
	}

	return { tags: [], key: "", label: targetLabel };
}
